package bbs.service.impl;

import java.util.Date;
import java.util.List;

import javax.annotation.Resource;

import bbs.entity.constants.Constants;
import bbs.entity.enums.*;
import bbs.entity.po.ForumArticle;
import bbs.entity.po.ForumComment;
import bbs.entity.po.UserMessage;
import bbs.entity.query.ForumArticleQuery;
import bbs.entity.query.UserMessageQuery;
import bbs.exception.BusinessException;
import bbs.mappers.ForumArticleMapper;
import bbs.mappers.ForumCommentMapper;
import bbs.mappers.UserMessageMapper;
import org.springframework.stereotype.Service;

import bbs.entity.query.LikeRecordQuery;
import bbs.entity.po.LikeRecord;
import bbs.entity.vo.PaginationResultVO;
import bbs.entity.query.SimplePage;
import bbs.mappers.LikeRecordMapper;
import bbs.service.LikeRecordService;
import bbs.utils.StringTools;
import org.springframework.transaction.annotation.Transactional;


/**
 * 点赞记录 业务接口实现
 */
@Service("likeRecordService")
public class LikeRecordServiceImpl implements LikeRecordService {

	@Resource
	private LikeRecordMapper<LikeRecord, LikeRecordQuery> likeRecordMapper;

	@Resource
	private UserMessageMapper<UserMessage, UserMessageQuery> userMessageMapper;

	@Resource
	private ForumArticleMapper<ForumArticle, ForumArticleQuery> forumArticleMapper;

	@Resource
	private ForumCommentMapper<ForumComment, ForumComment> forumCommentMapper;

	/**
	 * 根据条件查询列表
	 */
	@Override
	public List<LikeRecord> findListByParam(LikeRecordQuery param) {
		return this.likeRecordMapper.selectList(param);
	}

	/**
	 * 根据条件查询列表
	 */
	@Override
	public Integer findCountByParam(LikeRecordQuery param) {
		return this.likeRecordMapper.selectCount(param);
	}

	/**
	 * 分页查询方法
	 */
	@Override
	public PaginationResultVO<LikeRecord> findListByPage(LikeRecordQuery param) {
		int count = this.findCountByParam(param);
		int pageSize = param.getPageSize() == null ? PageSize.SIZE15.getSize() : param.getPageSize();

		SimplePage page = new SimplePage(param.getPageNo(), count, pageSize);
		param.setSimplePage(page);
		List<LikeRecord> list = this.findListByParam(param);
		PaginationResultVO<LikeRecord> result = new PaginationResultVO(count, page.getPageSize(), page.getPageNo(), page.getPageTotal(), list);
		return result;
	}

	/**
	 * 新增
	 */
	@Override
	public Integer add(LikeRecord bean) {
		return this.likeRecordMapper.insert(bean);
	}

	/**
	 * 批量新增
	 */
	@Override
	public Integer addBatch(List<LikeRecord> listBean) {
		if (listBean == null || listBean.isEmpty()) {
			return 0;
		}
		return this.likeRecordMapper.insertBatch(listBean);
	}

	/**
	 * 批量新增或者修改
	 */
	@Override
	public Integer addOrUpdateBatch(List<LikeRecord> listBean) {
		if (listBean == null || listBean.isEmpty()) {
			return 0;
		}
		return this.likeRecordMapper.insertOrUpdateBatch(listBean);
	}

	/**
	 * 多条件更新
	 */
	@Override
	public Integer updateByParam(LikeRecord bean, LikeRecordQuery param) {
		StringTools.checkParam(param);
		return this.likeRecordMapper.updateByParam(bean, param);
	}

	/**
	 * 多条件删除
	 */
	@Override
	public Integer deleteByParam(LikeRecordQuery param) {
		StringTools.checkParam(param);
		return this.likeRecordMapper.deleteByParam(param);
	}

	/**
	 * 根据OpId获取对象
	 */
	@Override
	public LikeRecord getLikeRecordByOpId(Integer opId) {
		return this.likeRecordMapper.selectByOpId(opId);
	}

	/**
	 * 根据OpId修改
	 */
	@Override
	public Integer updateLikeRecordByOpId(LikeRecord bean, Integer opId) {
		return this.likeRecordMapper.updateByOpId(bean, opId);
	}

	/**
	 * 根据OpId删除
	 */
	@Override
	public Integer deleteLikeRecordByOpId(Integer opId) {
		return this.likeRecordMapper.deleteByOpId(opId);
	}

	/**
	 * 根据ObjectIdAndUserIdAndOpType获取对象
	 */
	@Override
	public LikeRecord getLikeRecordByObjectIdAndUserIdAndOpType(String objectId, String userId, Integer opType) {
		return this.likeRecordMapper.selectByObjectIdAndUserIdAndOpType(objectId, userId, opType);
	}

	/**
	 * 根据ObjectIdAndUserIdAndOpType修改
	 */
	@Override
	public Integer updateLikeRecordByObjectIdAndUserIdAndOpType(LikeRecord bean, String objectId, String userId, Integer opType) {
		return this.likeRecordMapper.updateByObjectIdAndUserIdAndOpType(bean, objectId, userId, opType);
	}

	/**
	 * 根据ObjectIdAndUserIdAndOpType删除
	 */
	@Override
	public Integer deleteLikeRecordByObjectIdAndUserIdAndOpType(String objectId, String userId, Integer opType) {
		return this.likeRecordMapper.deleteByObjectIdAndUserIdAndOpType(objectId, userId, opType);
	}

	/**
	 * 点赞
	 * @param objectId
	 * @param userId
	 * @param nickName
	 * @param opTypeEnum
	 */
	@Override
	@Transactional
	public void doLike(String objectId, String userId, String nickName, OperRecordOpTypeEnum opTypeEnum) {
		UserMessage userMessage = new UserMessage();
		userMessage.setCreateTime(new Date());
		LikeRecord likeRecord = null;
		switch (opTypeEnum) {
//			1.文章点赞
			case ARTICLE_LIKE:
				ForumArticle forumArticle = forumArticleMapper.selectByArticleId(objectId);
				//1.1.判断文章是否存在
				if (forumArticle == null) throw new BusinessException(Constants.ARTICLE_NOT_EXISTS);
//				1.2.记录点赞数据
				articleLike(objectId, forumArticle, userId, opTypeEnum);

				userMessage.setArticleId(objectId);
				userMessage.setArticleTitle(forumArticle.getTitle());
				userMessage.setMessageType(MessageTypeEnum.ARTICLE_LIKE.getType());
				userMessage.setCommentId(Constants.ZERO);
				userMessage.setReceivedUserId(forumArticle.getUserId());
				break;

//			2.评论点赞
			case COMMENT_LIKE:
//				2.1.判断评论是否存在
				ForumComment forumComment = forumCommentMapper.selectByCommentId(Integer.valueOf(objectId));
				if (forumComment == null) throw new BusinessException(Constants.COMMENT_NOT_EXISTS);
//				2.2.记录评论数据
				commentLike(objectId, forumComment, userId, opTypeEnum);
				forumArticle = forumArticleMapper.selectByArticleId(forumComment.getArticleId());

				userMessage.setCommentId(forumComment.getCommentId());
				userMessage.setArticleId(forumComment.getArticleId());
				userMessage.setArticleTitle(forumArticle.getTitle());
				userMessage.setMessageType(MessageTypeEnum.COMMENT_LIKE.getType());
				userMessage.setReceivedUserId(forumComment.getUserId());
				userMessage.setMessageContent(forumComment.getContent());
				break;
		}

		userMessage.setSendUserId(userId);
		userMessage.setSendNickName(nickName);
		userMessage.setStatus(MessageStatusEnum.UNREAD.getStatus());
		if (!userId.equals(userMessage.getReceivedUserId())){
			UserMessage dbInfo = userMessageMapper.selectByArticleIdAndCommentIdAndSendUserIdAndMessageType(userMessage.getArticleId(), userMessage.getCommentId(), userMessage.getSendUserId(), userMessage.getMessageType());
			if (dbInfo == null) {
				userMessageMapper.insert(userMessage);
			}
		}
	}


	private void articleLike(String objectId, ForumArticle forumArticle, String userId, OperRecordOpTypeEnum opTypeEnum){
		LikeRecord likeRecord = likeRecordMapper.selectByObjectIdAndUserIdAndOpType(objectId, userId, opTypeEnum.getType());
		Integer changeCount = 0;
		if (likeRecord != null){
			changeCount = -1;
			likeRecordMapper.deleteByObjectIdAndUserIdAndOpType(objectId, userId, opTypeEnum.getType());
		} else {
			changeCount = 1;
			LikeRecord record = new LikeRecord();
			record.setUserId(userId);
			record.setObjectId(objectId);
			record.setOpType(opTypeEnum.getType());
			record.setCreateTime(new Date());
			record.setAuthorUserId(forumArticle.getUserId());
			likeRecordMapper.insert(record);
		}
		forumArticleMapper.updateArticleCount(objectId, UpdateArticleCountTypeEnum.GOOD_COUNT.getType(),changeCount);
	}

	private void commentLike(String objectId, ForumComment forumComment, String userId, OperRecordOpTypeEnum opTypeEnum){
		LikeRecord likeRecord = likeRecordMapper.selectByObjectIdAndUserIdAndOpType(objectId, userId, opTypeEnum.getType());
		Integer changeCount = 0;
		if (likeRecord != null){
			likeRecordMapper.deleteByObjectIdAndUserIdAndOpType(objectId, userId, opTypeEnum.getType());
			changeCount = -1;
		} else {
			LikeRecord record = new LikeRecord();
			record.setUserId(userId);
			record.setObjectId(objectId);
			record.setOpType(opTypeEnum.getType());
			record.setCreateTime(new Date());
			record.setAuthorUserId(forumComment.getUserId());
			likeRecordMapper.insert(record);
			changeCount = 1;
		}
		forumCommentMapper.updateCommentGoodCount(changeCount, Integer.parseInt(objectId));
	}
}